package protocol

import (
	"encoding/xml"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// MessageType GB28181消息类型
const (
	MessageTypeRegister      = "REGISTER"       // 设备注册
	MessageTypeKeepalive     = "KEEPALIVE"      // 心跳保活
	MessageTypeCatalog       = "CATALOG"        // 设备目录查询
	MessageTypeDeviceInfo    = "DEVICE_INFO"    // 设备信息查询
	MessageTypeDeviceStatus  = "DEVICE_STATUS"  // 设备状态查询
	MessageTypeDeviceControl = "DEVICE_CONTROL" // 设备控制
	MessageTypeRecordInfo    = "RECORD_INFO"    // 录像信息查询
	MessageTypeAlarm         = "ALARM"          // 报警信息
	MessageTypeBroadcast     = "BROADCAST"      // 广播
)

// GB28181Message GB28181协议消息结构
type GB28181Message struct {
	XMLName   xml.Name `xml:"Query"`
	CmdType   string   `xml:"CmdType"`             // 命令类型
	SN        string   `xml:"SN"`                  // 序列号
	DeviceID  string   `xml:"DeviceID"`            // 设备ID
	StartTime string   `xml:"StartTime,omitempty"` // 开始时间
	EndTime   string   `xml:"EndTime,omitempty"`   // 结束时间
	Secrecy   string   `xml:"Secrecy,omitempty"`   // 保密性
	Type      string   `xml:"Type,omitempty"`      // 类型
	PTZCmd    string   `xml:"PTZCmd,omitempty"`    // PTZ控制命令
	Info      string   `xml:"Info,omitempty"`      // 信息
}

// GB28181Response GB28181协议响应结构
type GB28181Response struct {
	XMLName    xml.Name `xml:"Response"`
	CmdType    string   `xml:"CmdType"`                   // 命令类型
	SN         string   `xml:"SN"`                        // 序列号
	DeviceID   string   `xml:"DeviceID"`                  // 设备ID
	Result     string   `xml:"Result"`                    // 结果
	Status     string   `xml:"Status,omitempty"`          // 状态
	Info       string   `xml:"Info,omitempty"`            // 信息
	RecordList []Record `xml:"RecordList>Item,omitempty"` // 录像列表
}

// Record 录像信息结构
type Record struct {
	DeviceID  string `xml:"DeviceID"`  // 设备ID
	Name      string `xml:"Name"`      // 录像名称
	Address   string `xml:"Address"`   // 录像地址
	StartTime string `xml:"StartTime"` // 开始时间
	EndTime   string `xml:"EndTime"`   // 结束时间
	Secrecy   string `xml:"Secrecy"`   // 保密性
	Type      string `xml:"Type"`      // 类型
	FileSize  string `xml:"FileSize"`  // 文件大小
}

// DeviceInfo 设备信息结构
type DeviceInfo struct {
	DeviceID     string `xml:"DeviceID"`     // 设备ID
	Name         string `xml:"Name"`         // 设备名称
	Manufacturer string `xml:"Manufacturer"` // 厂商
	Model        string `xml:"Model"`        // 型号
	Owner        string `xml:"Owner"`        // 归属
	CivilCode    string `xml:"CivilCode"`    // 行政区域
	Address      string `xml:"Address"`      // 安装地址
	Parental     string `xml:"Parental"`     // 父设备ID
	ParentID     string `xml:"ParentID"`     // 父设备ID
	SafetyWay    string `xml:"SafetyWay"`    // 安全方式
	RegisterWay  string `xml:"RegisterWay"`  // 注册方式
	CertNum      string `xml:"CertNum"`      // 证书序列号
	Certifiable  string `xml:"Certifiable"`  // 是否支持证书
	ErrCode      string `xml:"ErrCode"`      // 错误代码
	EndTime      string `xml:"EndTime"`      // 结束时间
	Secrecy      string `xml:"Secrecy"`      // 保密性
	IPAddress    string `xml:"IPAddress"`    // IP地址
	Port         string `xml:"Port"`         // 端口
	Password     string `xml:"Password"`     // 密码
	Status       string `xml:"Status"`       // 状态
	Longitude    string `xml:"Longitude"`    // 经度
	Latitude     string `xml:"Latitude"`     // 纬度
}

// ParseMessage 解析GB28181协议消息（支持SIP和XML格式）
func ParseMessage(data []byte) (*GB28181Message, error) {
	var msg GB28181Message

	// 首先检查是否是SIP协议消息
	if IsSIPMessage(data) {
		sipMsg, err := ParseSIPMessage(data)
		if err != nil {
			return nil, fmt.Errorf("SIP消息解析失败: %v", err)
		}

		// 如果是SIP MESSAGE，提取GB28181消息体
		if sipMsg.Method == SIPMethodMESSAGE && sipMsg.Body != "" {
			gbData, err := ConvertSIPToGB28181(sipMsg)
			if err != nil {
				return nil, fmt.Errorf("从SIP消息提取GB28181内容失败: %v", err)
			}
			
			// 递归解析GB28181消息
			return ParseMessage(gbData)
		}

		// 对于其他SIP方法，构建简化的GB28181消息
		msg.CmdType = strings.ToUpper(sipMsg.Method)
		
		// 从SIP URI中提取设备ID
		if sipMsg.To != "" {
			deviceID, err := ExtractDeviceIDFromSIPURI(sipMsg.To)
			if err == nil {
				msg.DeviceID = deviceID
			}
		}
		
		return &msg, nil
	}

	// 检查是否是XML格式
	if strings.Contains(string(data), "<?xml") || strings.Contains(string(data), "<Query") {
		err := xml.Unmarshal(data, &msg)
		if err != nil {
			return nil, fmt.Errorf("XML解析失败: %v", err)
		}
		return &msg, nil
	}

	// 如果是简单文本格式，尝试解析
	strData := strings.TrimSpace(string(data))
	if strings.Contains(strData, ":") {
		parts := strings.SplitN(strData, ":", 2)
		if len(parts) == 2 {
			msg.CmdType = strings.ToUpper(parts[0])
			msg.DeviceID = strings.TrimSpace(parts[1])
			return &msg, nil
		}
	}

	return nil, fmt.Errorf("无法解析的消息格式: %s", strData)
}

// BuildResponse 构建GB28181协议响应（支持SIP和XML格式）
func BuildResponse(cmdType, sn, deviceID, result, status, info string, useSIPFormat bool, sipFrom, sipTo, sipCallID string) ([]byte, error) {
	response := GB28181Response{
		CmdType:  cmdType,
		SN:       sn,
		DeviceID: deviceID,
		Result:   result,
		Status:   status,
		Info:     info,
	}

	data, err := xml.MarshalIndent(response, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("XML序列化失败: %v", err)
	}

	gbData := append([]byte(xml.Header), data...)

	// 如果需要SIP格式，将GB28181消息包装为SIP MESSAGE
	if useSIPFormat && sipFrom != "" && sipTo != "" && sipCallID != "" {
		return ConvertGB28181ToSIP(gbData, sipFrom, sipTo, sipCallID), nil
	}

	return gbData, nil
}

// BuildCatalogResponse 构建设备目录响应
func BuildCatalogResponse(sn, deviceID string, devices []DeviceInfo) ([]byte, error) {
	response := GB28181Response{
		CmdType:  MessageTypeCatalog,
		SN:       sn,
		DeviceID: deviceID,
		Result:   "OK",
	}

	// 这里简化处理，实际应该包含设备列表
	if len(devices) > 0 {
		response.Info = fmt.Sprintf("找到 %d 个设备", len(devices))
	} else {
		response.Info = "未找到设备"
	}

	data, err := xml.MarshalIndent(response, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("XML序列化失败: %v", err)
	}

	return append([]byte(xml.Header), data...), nil
}

// BuildDeviceInfoResponse 构建设备信息响应
func BuildDeviceInfoResponse(sn, deviceID, name, manufacturer, model, status string) ([]byte, error) {
	response := GB28181Response{
		CmdType:  MessageTypeDeviceInfo,
		SN:       sn,
		DeviceID: deviceID,
		Result:   "OK",
		Status:   status,
		Info:     fmt.Sprintf("设备名称: %s, 厂商: %s, 型号: %s", name, manufacturer, model),
	}

	data, err := xml.MarshalIndent(response, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("XML序列化失败: %v", err)
	}

	return append([]byte(xml.Header), data...), nil
}

// BuildKeepaliveResponse 构建心跳响应
func BuildKeepaliveResponse(sn, deviceID string) ([]byte, error) {
	response := GB28181Response{
		CmdType:  MessageTypeKeepalive,
		SN:       sn,
		DeviceID: deviceID,
		Result:   "OK",
	}

	data, err := xml.MarshalIndent(response, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("XML序列化失败: %v", err)
	}

	return append([]byte(xml.Header), data...), nil
}

// BuildRegisterResponse 构建注册响应
func BuildRegisterResponse(sn, deviceID string) ([]byte, error) {
	response := GB28181Response{
		CmdType:  MessageTypeRegister,
		SN:       sn,
		DeviceID: deviceID,
		Result:   "OK",
	}

	data, err := xml.MarshalIndent(response, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("XML序列化失败: %v", err)
	}

	return append([]byte(xml.Header), data...), nil
}

// GenerateSN 生成序列号
func GenerateSN() string {
	return fmt.Sprintf("%d", time.Now().UnixNano())
}

// IsValidMessageType 检查消息类型是否有效
func IsValidMessageType(msgType string) bool {
	switch msgType {
	case MessageTypeRegister, MessageTypeKeepalive, MessageTypeCatalog,
		MessageTypeDeviceInfo, MessageTypeDeviceStatus, MessageTypeDeviceControl,
		MessageTypeRecordInfo, MessageTypeAlarm, MessageTypeBroadcast:
		return true
	default:
		return false
	}
}

// GetMessageTypeDescription 获取消息类型描述
func GetMessageTypeDescription(msgType string) string {
	switch msgType {
	case MessageTypeRegister:
		return "设备注册"
	case MessageTypeKeepalive:
		return "心跳保活"
	case MessageTypeCatalog:
		return "设备目录查询"
	case MessageTypeDeviceInfo:
		return "设备信息查询"
	case MessageTypeDeviceStatus:
		return "设备状态查询"
	case MessageTypeDeviceControl:
		return "设备控制"
	case MessageTypeRecordInfo:
		return "录像信息查询"
	case MessageTypeAlarm:
		return "报警信息"
	case MessageTypeBroadcast:
		return "广播"
	default:
		return "未知消息类型"
	}
}

// BuildDeviceControlMessage 构建设备控制消息
func BuildDeviceControlMessage(deviceID, channelID, ptzCommand, description string) ([]byte, error) {
	// 构建GB28181设备控制查询消息
	query := GB28181Message{
		CmdType:  MessageTypeDeviceControl,
		SN:       GenerateSN(),
		DeviceID: deviceID,
	}

	// 如果是PTZ控制，添加PTZCmd字段
	if strings.HasPrefix(ptzCommand, "A2F") {
		query.PTZCmd = ptzCommand
	}

	// 添加通道ID（如果有）
	// if channelID != "" {
	// 	query.ChannelID = channelID
	// }

	// 添加描述信息
	if description != "" {
		query.Info = description
	}

	data, err := xml.MarshalIndent(query, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("XML序列化失败: %v", err)
	}

	return append([]byte(xml.Header), data...), nil
}

// BuildPTZControlMessage 构建PTZ控制消息
func BuildPTZControlMessage(deviceID, channelID, command string, speed int32) ([]byte, error) {
	// 构建PTZ命令字符串
	ptzCmd := fmt.Sprintf("A2F%s%02d", command, speed)

	return BuildDeviceControlMessage(deviceID, channelID, ptzCmd, fmt.Sprintf("PTZ控制: %s, 速度: %d", command, speed))
}

// BuildDeviceControlResponse 构建设备控制响应
func BuildDeviceControlResponse(sn, deviceID, result, status, info string) ([]byte, error) {
	return BuildResponse(MessageTypeDeviceControl, sn, deviceID, result, status, info, false, "", "", "")
}

// ParsePTZCommand 解析PTZ命令
func ParsePTZCommand(ptzCmd string) (command string, speed int32, err error) {
	if len(ptzCmd) < 5 || !strings.HasPrefix(ptzCmd, "A2F") {
		return "", 0, fmt.Errorf("无效的PTZ命令格式: %s", ptzCmd)
	}

	// 提取命令代码
	cmdCode := ptzCmd[3:5]

	// 提取速度
	speedStr := ptzCmd[5:]
	speedVal, err := strconv.ParseInt(speedStr, 10, 32)
	if err != nil {
		return "", 0, fmt.Errorf("无效的速度值: %s", speedStr)
	}

	// 映射命令代码到命令名称
	switch cmdCode {
	case "01":
		command = "left"
	case "02":
		command = "right"
	case "03":
		command = "up"
	case "04":
		command = "down"
	case "05":
		command = "zoom_in"
	case "06":
		command = "zoom_out"
	case "07":
		command = "focus_near"
	case "08":
		command = "focus_far"
	case "09":
		command = "iris_open"
	case "0A":
		command = "iris_close"
	case "00":
		command = "stop"
	default:
		return "", 0, fmt.Errorf("未知的PTZ命令代码: %s", cmdCode)
	}

	return command, int32(speedVal), nil
}
